package com.telecom.oil.smart.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.ocr_api20210707.Client;
import com.aliyun.ocr_api20210707.models.RecognizeBasicRequest;
import com.aliyun.ocr_api20210707.models.RecognizeBasicResponse;
import com.aliyun.teautil.models.RuntimeOptions;
import com.telecom.oil.smart.api.vo.OcrRecognizeResult;
import com.telecom.oil.smart.service.AliyunOcrRecognizeBasicService;
import info.debatty.java.stringsimilarity.JaroWinkler;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


@Slf4j
@Service
public class AliyunOcrRecognizeBasicServiceImpl implements AliyunOcrRecognizeBasicService{

	@Value("${aliyun.ocr.accessKeyId}")
	private String accessKeyId;

	@Value("${aliyun.ocr.accessKeySecret}")
	private String accessKeySecret;

	@Value("${aliyun.ocr.endpoint}")
	private String endpoint;

	private com.aliyun.ocr_api20210707.Client createClient(String accessKeyId, String accessKeySecret, String endpoint) {
		com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config()
				// 必填，您的 AccessKey ID
				.setAccessKeyId(accessKeyId)
				// 必填，您的 AccessKey Secret
				.setAccessKeySecret(accessKeySecret);
		// 访问的域名
		config.endpoint = endpoint;
		Client client = null;
		try {
			client = new com.aliyun.ocr_api20210707.Client(config);
		} catch (Exception e) {
			log.error("OCR识别生成客户端错误");
			e.printStackTrace();
		}
		return client;
	}

	@Override
	public OcrRecognizeResult recognizeBasic(String url) {
		OcrRecognizeResult ocrRecognizeResult = new OcrRecognizeResult();
		log.info("请求参数url:{}", url);
		// 工程代码泄露可能会导致AccessKey泄露，并威胁账号下所有资源的安全性。以下代码示例仅供参考，建议使用更安全的 STS 方式，更多鉴权访问方式请参见：https://help.aliyun.com/document_detail/378657.html
		Client client = createClient(accessKeyId, accessKeySecret, endpoint);
		RecognizeBasicRequest recognizeBasicRequest = new RecognizeBasicRequest().setUrl(url);
		try {
			//OCR识别
			RecognizeBasicResponse response = client.recognizeBasicWithOptions(recognizeBasicRequest, new RuntimeOptions());
			String returnData = response.body.getData().trim();
			log.info("OCR识别API返回结果, result:{}", returnData);
			if(StringUtils.isEmpty(returnData)){
				log.error("OCR识别内容为空");
				return ocrRecognizeResult;
			}
			JSONObject jsonObject = JSON.parseObject(returnData);
			String content = ((String) jsonObject.get("content"));
			log.info("OCR识别结果内容, result:{}", content);

			String cardNumber = extractCardNumber(content);
			String receivedAmount = extractValue(content, "实收金额：");
			String cardBalance = extractValue(content, "卡片余额：");

			ocrRecognizeResult.setCardNumber(cardNumber);
			ocrRecognizeResult.setReceivedAmount(BigDecimal.valueOf(Double.parseDouble(receivedAmount)));
			ocrRecognizeResult.setCardBalance(BigDecimal.valueOf(Double.parseDouble(cardBalance)));
		} catch (Exception e) {
			log.error("OCR访问接口异常,exception:{}", e);
		}
		return ocrRecognizeResult;
	}

	/**
	 * 提取卡号
	 * @param content
	 * @return
	 */
	private String extractCardNumber(String content) {
		if(StringUtils.isEmpty(content)){
			return null;
		}
		String pattern = "\\b\\d{16}\\b"; // 使用正则表达式匹配16位数字

		Pattern regexPattern = Pattern.compile(pattern);
		Matcher matcher = regexPattern.matcher(content);
		if (matcher.find()) {
			return matcher.group(0);
		}
		return null;
	}

	/**
	 * 利用Jaro-Winkler相似度算法提取数值
	 * @param text
	 * @param keyword
	 * @return
	 */
	private String extractValue(String text, String keyword) {
		JaroWinkler jw = new JaroWinkler();
		String[] words = text.split(" ");
		double maxSimilarity = 0.0;
		String extractedValue = null;

		for (String word : words) {
			double similarity = jw.similarity(word, keyword);
			if (similarity > maxSimilarity) {
				maxSimilarity = similarity;
				extractedValue = word;
			}
		}
		// 移除字符串中的非数字字符
		String returnValue = extractedValue.replaceAll("[^0-9.]", "");
		return returnValue;
	}

}
